﻿using DocBot.Objects;
using DocBot.Util.Collections;

using GalaSoft.MvvmLight;

using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;

namespace DocBot.Util
{
	public class Settings : ObservableObject
	{
		private static string configFileName = "Settings.xml";

		private static object oSyncRoot = new Object();
		private static volatile Settings _instance = null;

		public static Settings Instance
		{
			get
			{
				if (_instance == null)
				{
					lock (oSyncRoot)
					{
						if (_instance == null)
						{
							_instance = new Settings();
							//check for config file, if exists: import config file
							if (File.Exists(Instance.configFilePath + "\\" + configFileName))
							{
								Instance.LoadConfig();
							}
							//if not, load default and save file
							else
							{
								if (File.Exists(Instance.configFilePath + "\\Backup\\" + configFileName))
								{
									Instance.LoadConfig(Instance.configFilePath + "\\Backup\\" + configFileName);
								}
								else
									getDefaultConfigFile();
							}
							if (Instance != null)
							{
								if (Instance.Pastebin_Mail != null)
									Instance.Valid_PasteBin_Mail = EmailValidator.ValidateEmails(new List<String> { Instance.Pastebin_Mail });
								if (Instance.Youtube_Mail != null)
									Instance.Valid_Youtube_Mail = EmailValidator.ValidateEmails(new List<String> { Instance.Youtube_Mail });
							}
						}
					}
					Messenger.Instance.Messages.Enqueue(new Message("Settings initialized", MessageType.Log));
				}
				return _instance;
			}
		}

		#region Properties
		// properties with private setter can't be serialized
		#region XmlIgnore
		[XmlIgnore]
		internal bool Valid_PasteBin_Mail { get; set; }

		[XmlIgnore]
		internal bool Valid_Youtube_Mail { get; set; }

		[XmlIgnore]
		public String configFilePath { get; private set; }
		[XmlIgnore]
		public bool IsDefaultConfig { get; private set; }
		#endregion

		public string IRC_Username { get; set; }

		public string IRC_Serveradress { get; set; }

		public int IRC_Serverport { get; set; }

		public string IRC_Password { get; set; }

		private bool _IRC_AutoConnect;
		public bool IRC_AutoConnect
		{
			get { return _IRC_AutoConnect; }
			set { _IRC_AutoConnect = value; }

		}

		public string IRC_TargetChannel { get; set; }

		public string IRC_QuitMessage { get; set; }
		/// <summary>
		/// Silence the whole bot
		/// </summary>
		public bool Silent { get; set; }
		public string VLC_LibVlcDllPath { get; set; }
		public string VLC_LibVlcPluginPath { get; set; }

		public string VLC_MediaPlayerWaveOutDevice { get; set; }
		public double VLC_MediaPlayerVolume { get; set; }
		/// <summary>
		/// true = Playback enabled, false = Playback disabled
		/// </summary>
		public bool VLC_MediaPlayerSilent { get; set; }

		public string VLC_FollowerWaveOutDevice { get; set; }
		public double VLC_FollowerVolume { get; set; }
		/// <summary>
		/// true = Playback enabled, false = Playback disabled
		/// </summary>
		public bool VLC_FollowerSilent { get; set; }

		public string VLC_SubScriberWaveOutDevice { get; set; }
		public double VLC_SubScriberVolume { get; set; }
		/// <summary>
		/// true = Playback enabled, false = Playback disabled
		/// </summary>
		public bool VLC_SubScriberSilent { get; set; }

		public string VLC_SoundboardWaveOutDevice { get; set; }
		public double VLC_SoundboardVolume { get; set; }
		/// <summary>
		/// true = Playback enabled, false = Playback disabled
		/// </summary>
		public bool VLC_SoundboardSilent { get; set; }

		public Playmode VLC_PlayBackType { get; set; }

		public int Media_AutoSkipThreshold { get; set; }

		public int Media_MaxVoteCounter { get; set; }

		public int Media_MaxSongDuration { get; set; }

		public string Pastebin_DevKey { get; set; }

		public string Pastebin_Mail { get; set; }

		public string Pastebin_Password { get; set; }

		public string Youtube_Mail { get; set; }

		public string Youtube_API_JSON { get; set; }

		public string BackupDirectory { get; set; }

		public bool DebugMode { get; set; }

		public bool SaveLog { get; set; }

		public bool AutoConnect { get; set; }

		public bool ReplyToChat { get; set; }

		public bool SaveChat { get; set; }

		#endregion

		#region Construction
		private Settings()
		{
			configFilePath = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\DocBot";
			checkPath();
		}

		~Settings()
		{
			checkPath();
			saveConfigFile();
		}
		#endregion

		#region Methods

		#region Validation
		private static void ValidateStringValues()
		{
			if (_instance.IRC_Username == null | _instance.IRC_Username == String.Empty)
				_instance.IRC_Username = "username"; // irc/twitch loginname

			if (_instance.IRC_Password == null | _instance.IRC_Password == String.Empty)
				_instance.IRC_Password = "password"; // oauth token

			if (_instance.IRC_TargetChannel == null | _instance.IRC_TargetChannel == String.Empty)
				_instance.IRC_TargetChannel = "#insirethomson"; // irc channel

			if (_instance.IRC_Serveradress == null | _instance.IRC_Serveradress == String.Empty)
				_instance.IRC_Serveradress = "irc.twitch.tv";

			if (_instance.VLC_LibVlcDllPath == null | _instance.VLC_LibVlcDllPath == String.Empty)
				_instance.VLC_LibVlcDllPath = @"VlcPortable\";

			if (_instance.VLC_LibVlcPluginPath == null | _instance.VLC_LibVlcPluginPath == String.Empty)
				_instance.VLC_LibVlcPluginPath = @"VlcPortable\plugins\";

			if (_instance.VLC_MediaPlayerWaveOutDevice == null | _instance.VLC_MediaPlayerWaveOutDevice == String.Empty)
				_instance.VLC_MediaPlayerWaveOutDevice = "Line 1 (Virtual Audio Cable) ($1,$64)";

			if (_instance.VLC_FollowerWaveOutDevice == null | _instance.VLC_FollowerWaveOutDevice == String.Empty)
				_instance.VLC_FollowerWaveOutDevice = "Line 1 (Virtual Audio Cable) ($1,$64)";

			if (_instance.VLC_SubScriberWaveOutDevice == null | _instance.VLC_SubScriberWaveOutDevice == String.Empty)
				_instance.VLC_SubScriberWaveOutDevice = "Line 1 (Virtual Audio Cable) ($1,$64)";

			if (_instance.VLC_SoundboardWaveOutDevice == null | _instance.VLC_SoundboardWaveOutDevice == String.Empty)
				_instance.VLC_SoundboardWaveOutDevice = "Line 1 (Virtual Audio Cable) ($1,$64)";

			if (_instance.Pastebin_Mail == null | _instance.Pastebin_Mail == String.Empty)
				_instance.Pastebin_Mail = "mail";

			if (_instance.Pastebin_Password == null | _instance.Pastebin_Password == String.Empty)
				_instance.Pastebin_Password = "pw";

			if (_instance.Youtube_Mail == null | _instance.Youtube_Mail == String.Empty)
				_instance.Youtube_Mail = "mail";

			if (_instance.Youtube_API_JSON == null | _instance.Youtube_API_JSON == String.Empty)
				_instance.Youtube_API_JSON = @"client_secret.json";

			if (_instance.BackupDirectory == null | _instance.BackupDirectory == String.Empty)
				_instance.BackupDirectory = @"Backup\";
		}

		private static void validateNumberValues()
		{
			if (_instance.VLC_MediaPlayerVolume < 1)
				_instance.VLC_MediaPlayerVolume = 50;
			if (_instance.VLC_FollowerVolume < 1)
				_instance.VLC_FollowerVolume = 50;
			if (_instance.VLC_SubScriberVolume < 1)
				_instance.VLC_SubScriberVolume = 50;
			if (_instance.VLC_SoundboardVolume < 1)
				_instance.VLC_SoundboardVolume = 50;

			if (_instance.IRC_Serverport < 1)
				_instance.IRC_Serverport = 6667;

			if (_instance.Media_AutoSkipThreshold < 1)
				_instance.Media_AutoSkipThreshold = 360;
			if (_instance.Media_MaxVoteCounter < 1)
				_instance.Media_MaxVoteCounter = 10;
			if (_instance.Media_MaxSongDuration < 1)
				_instance.Media_MaxSongDuration = 360;
		}
		#endregion

		public void createBackup()
		{
			String[] files = Directory.GetFiles(configFilePath);
			for (int i = 0; i < files.Length; i++)
			{
				string s = Settings.Instance.BackupDirectory + "\\" + Path.GetFileName(files[i]);
				File.Copy(files[i], s, true);
			}
			Messenger.Instance.Messages.Enqueue(new Message("Backup created @ " + configFilePath, MessageType.Log));
		}

		public void LoadConfig()
		{
			XmlSerializer deserializer = new XmlSerializer(typeof(Settings));
			TextReader textReader = new StreamReader(configFilePath + "\\" + configFileName);
			_instance = (Settings)deserializer.Deserialize(textReader);
			textReader.Close();
			if (_instance == null)
			{
				_instance = new Settings();
				getDefaultConfigFile();
			}
			else
				_instance.IsDefaultConfig = false;
		}

		public void LoadConfig(string path)
		{
			XmlSerializer deserializer = new XmlSerializer(typeof(Settings));
			TextReader textReader = new StreamReader(path);
			_instance = (Settings)deserializer.Deserialize(textReader);
			textReader.Close();
			if (_instance == null)
			{
				_instance = new Settings();
				getDefaultConfigFile();
			}
			else
				_instance.IsDefaultConfig = false;

			ValidateStringValues();
			validateNumberValues();
		}

		private void saveConfigFile()
		{
			ValidateStringValues();
			validateNumberValues();
			XmlSerializer s = new XmlSerializer(typeof(Settings));
			TextWriter writer = new StreamWriter(configFilePath + "\\" + configFileName);
			s.Serialize(writer, Settings.Instance);
			writer.Close();
		}

		private void checkPath()
		{
			if (Directory.Exists(configFilePath)) return;
			else
				Directory.CreateDirectory(configFilePath);
		}

		private static void getDefaultConfigFile()
		{
			ValidateStringValues();
			validateNumberValues();

			_instance.IRC_AutoConnect = false;
			_instance.Silent = false;

			_instance.VLC_MediaPlayerSilent = true;
			_instance.VLC_FollowerSilent = false;
			_instance.VLC_SubScriberSilent = false;
			_instance.VLC_SoundboardSilent = false;

			_instance.VLC_PlayBackType = Playmode.PlayAll;

			_instance.Pastebin_DevKey = String.Empty;
			_instance.Pastebin_Mail = "mail";
			_instance.Pastebin_Password = "pw";
			_instance.Youtube_Mail = "mail";
			_instance.Youtube_API_JSON = @"client_secret.json";
			_instance.DebugMode = false;

			_instance.SaveChat = false;
			_instance.SaveLog = true;
			_instance.IsDefaultConfig = true;
			_instance.IRC_QuitMessage = String.Empty;
		}
		#endregion
	}
}
